<?php

namespace App\Http\Middleware;

use App\Exceptions\ErpException;
use App\Http\Controllers\Warehouse\PackageController;
use App\Libraries\Sign\Md5;
use App\Models\Customer;
use Carbon\Carbon;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use LTools\Facades\Sign;

class ErpMiddleware
{

    /**
     * @var null|Customer
     */
    static public $customer = null;

    /**
     * @var array
     */
    static public $body = [];

    /**
     * @var string[]
     */
    static protected $typeList = ['order.create', 'order.cancel', 'order.stop'];

    /**
     * @var null
     */
    static public $type = null;

    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure $next
     * @return mixed
     * @throws ErpException
     */
    public function handle(Request $request, Closure $next)
    {
        $this->body($request);
        return $next($request);
    }


    /**
     * @param Request $request
     * @return void
     * @throws ErpException
     */
    protected function body(Request $request)
    {
        if ($request->getContentType() !== 'json') {
            throw new ErpException("Content-Type 错误！");
        }

        if(!$request->expectsJson()){
            throw new ErpException("Accept 错误！");
        }

        try {
            $data = \GuzzleHttp\json_decode(request()->getContent(), true);
            if(empty($data)){
                throw new ErpException('无效参数');
            }

            $this->verifyType($data);

            $this->verifyTimestamp($data);

            $body = $this->verifyData($data);

            $customer = $this->verifyCode($data);

            try {
                $sign = new Md5($customer->docking->getAttribute('secret'));

                if (!$sign->verify($data, $data['sign'])) {
                    throw new ErpException('签名验证失败！');
                }
            } catch (\Exception $exception) {
                throw new ErpException($exception->getMessage());
            }

            $request->merge([
                'customer_id' => $customer->getKey()
            ]);

            static::$customer = $customer;
            static::$body = $body;
            static::$type = $data['type'];

        } catch (\GuzzleHttp\Exception\InvalidArgumentException $exception) {
            throw new ErpException('请求格式不正确！');
        }
    }

    /**
     * @param array $data
     * @return Customer
     * @throws ErpException
     */
    protected function verifyCode(array $data)
    {
        if (!isset($data['customer_code'])) {
            throw new ErpException('customer_code 参数必填！');
        }

        /** @var Customer $customer */
        $customer = Customer::query()->where('code', '=', $data['customer_code'])->first();
        if (is_null($customer)) {
            throw new ErpException('customer_code 不存在');
        }

        if (!$customer->isAvailable()) {
            throw new ErpException('客户不可用！');
        }
        return $customer->loadMissing(['docking']);
    }


    /**
     * @param $data
     * @return mixed
     * @throws ErpException
     */
    protected function verifyData($data)
    {
        if (!isset($data['data'])) {
            throw new ErpException('data 参数必填！');
        }

        try {
            $body = base64_decode($data['data']);
            if($body === false){
                throw new ErpException('data 不是有效的base64编码！');
            }

            return \GuzzleHttp\json_decode($body, true);

        } catch (\GuzzleHttp\Exception\InvalidArgumentException $exception) {
            throw new ErpException('data 参数不正确！');
        }
    }


    /**
     * 验证时间.
     *
     * @method validateTimestamp
     *
     * @param $data
     * @return void
     *
     * @throws ErpException
     * @author luffyzhao@vip.126.com
     */
    private function verifyTimestamp($data)
    {
        if (!isset($data['timestamp'])) {
            throw new ErpException('timestamp 参数必填！');
        }

        if(Carbon::createFromTimestamp($data['timestamp'])->diffInRealSeconds() <= 60){
            throw new ErpException('timestamp 相关不能超过60秒！');
        }
    }

    /**
     * @param $data
     * @return void
     * @throws ErpException
     */
    private function verifyType($data)
    {
        if (!isset($data['type'])) {
            throw new ErpException('type 参数必填！');
        }

        if (!in_array($data['type'], static::$typeList)) {
            throw new ErpException('type 参数不正确！');
        }
    }


}
